Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support more quadratic solvers #2574

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open

Conversation

pet-mit
Copy link
Contributor

@pet-mit pet-mit commented Jan 13, 2025

This PR adds the possibility for the user to choose quadratic (QP) solvers other than sirius, dor adequacy problems.
It does so by interfacing Antares QP description (PROBLEME_ANTARES_A_RESOUDRE) to the new OR-Tools MathOpt API.

The new "quadratic-solver" parameter allows the user to switch solver:

  • setting the value "sirius" will make Antares behave like before, by shunting OR-Tools and calling sirius directly
  • setting another value will make Antares use OR-Tools via the MathOpt API. For now, only "pdlp" is supported: SCIP seems to be broken (see here) and XPRESS has not been yet added (see here)

Breaking change:

  • "ortools-solver" parameter has been renamed to "linear-solver"
  • "solver-parameters" parameter has been renamed to "linear-solver-parameters"
  • New parameters have been added : "quadratic-solver" and "quadratic-solver-parameters" (note that the last parameter is a placeholder, and that is not used for now)

Signed-off-by: Peter Mitri <[email protected]>
@pet-mit pet-mit added the breaking change This PR/issue introduces a breaking change for users label Jan 13, 2025
{
if (options.quadraticSolver != "sirius")
{
const std::string notFound = "Solver " + options.quadraticSolver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t understand this condition

@@ -35,23 +35,43 @@

using namespace operations_research;

enum SolverClass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use enum class

Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
@pet-mit pet-mit marked this pull request as ready for review January 21, 2025 13:29
@pet-mit pet-mit changed the title Support multiple quadratic solvers Support more quadratic solvers Jan 21, 2025
Signed-off-by: Peter Mitri <[email protected]>
@pet-mit pet-mit requested a review from a team January 21, 2025 13:35
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
@@ -12,6 +12,7 @@ toc_depth: 2
* Short term storage costs [ANT-1854] (#2302)
* Add ts-generation for links [ANT-1084] (#1986)
* Make it possible to specify the final hydro reservoir level [ANT-1084] (#1521)
* Add support for more QP solvers [ANT-2546] (#2574)
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About QP : don't hesitate to be more explicit and indicate quadratic problem as in the PR's title

std::string linearSolverName = study_.parameters.optOptions.linearSolver;
file_content.addItemToSection("study", "linear solver", linearSolverName);

std::string quadraticSolverName = study_.parameters.optOptions.linearSolver;
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About line :

std::string quadraticSolverName = study_.parameters.optOptions.linearSolver;

By any chance, would you mean (instead) :

std::string quadraticSolverName = study_.parameters.optOptions.quadraticSolver;

?

Comment on lines +1286 to 1292
optOptions.linearSolver = options.optOptions.linearSolver;
optOptions.linearSolverParameters = options.optOptions.linearSolverParameters;
optOptions.quadraticSolver = options.optOptions.quadraticSolver;
optOptions.quadraticSolverParameters = options.optOptions.quadraticSolverParameters;

// Options that can be set both in command-line and file
optOptions.solverLogs = options.optOptions.solverLogs || optOptions.solverLogs;
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of these 5 lines, it would be better to have :

optOptions = options.optOptions;

But because of the last line, it seems we can't do that.
But we may if we define an overloading operator in struct OptimizationOptions, with a special treatment for attribute solverLogs.
This operator could be "=" or "<<"

@@ -48,7 +48,10 @@ namespace
{
void printSolvers()
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the scope of this PR ? (not sure)

printSolvers() :

  • Should be renamed into : logAllAvailableSolvers()
  • why do we print to std::cout and not in usual logs ? Does it even make sense ?

Moreover printSolvers is called from handleOptions which has a very non expressive and probably wrong name and, besides printing, does very strange things.

@@ -48,7 +48,10 @@ namespace
{
void printSolvers()
{
std::cout << "Available solvers: " << availableOrToolsSolversString() << std::endl;
std::cout << "Available linear solvers: " // NOSONAR
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NOSONAR : what do we mean by that ?

@@ -276,6 +278,7 @@ BOOST_FIXTURE_TEST_CASE(On_year_9__RHS_TS_number_4_is_taken_into_account, StudyW

OutputRetriever output(simulation->rawSimu());
BOOST_TEST(output.flow(link).hour(0) == 40., tt::tolerance(0.001));
BOOST_TEST(output.flow(link).hour(0) == 40., tt::tolerance(0.001));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplication here

Comment on lines +8 to +9
INCLUDE
"${CMAKE_SOURCE_DIR}/solver/utils"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

INCLUDE
"${CMAKE_SOURCE_DIR}/solver/utils"

is this useful ?
I mean : if we link with Antares::solverUtils, related include directory should be automatic

Comment on lines +43 to +44
problemeAResoudre.Sens = {};
problemeAResoudre.IndicesDebutDeLigne = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we give to some problemeAResoudre's data members an empty value.
We don't need that : these data members are empty by default at creation.

}
};

BOOST_AUTO_TEST_SUITE(tests_on_ortools_quadratic_wrapper)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As all your unit tests use the same fixture, you could use :

BOOST_FIXTURE_TEST_SUITE(tests_on_ortools_quadratic_wrapper, QpFixture);

BOOST_AUTO_TEST_CASE(test_case1)
{...}

BOOST_AUTO_TEST_CASE(test_case2)
{...}
...
BOOST_AUTO_TEST_SUITE_END()

As you can see, no need to pass the fixture for each test case


BOOST_FIXTURE_TEST_CASE(solver_not_supported, QpFixture)
{
options.quadraticSolver = "sirius";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I look at the fixture (the part that does not "check" anything), I wish it could be turned into an class QuadraticProblem.
If this is possible, in unit tests we could have :

BOOST_FIXTURE_TEST_CASE(simple_qp_one_var, QpFixture)
{
    QuadraticProblem QP(/*whatever needed*/);
    QP.addVariable("x", 0, 1, -0.5, 1);
    QP.solve();
    BOOST_CHECK(QP.success());
    BOOST_TEST(QP.solution() == {0.25});
    ....
}

Instead, we have to manipulate problemeAResoudre things, we don't want to read about as a user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change This PR/issue introduces a breaking change for users size/XXL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants